package io.xxx.omni.osc.sync

import com.alibaba.fastjson.JSONObject
import io.xxx.omni.osc.common.toJSONObject
import io.xxx.omni.osc.common.toLocalDateTime
import io.xxx.omni.osc.domain.*
import io.xxx.omni.osc.sdk.AkcClient
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Component
import java.time.LocalDateTime

/**
 * 爱库存
 */
// https://open.aikucun.com/delivery
abstract class AkcPorter : GenericPageDocumentPorter(), PlatformIdentity.AiKuCun {

    @Autowired
    protected lateinit var akcActivityRepository: AkcActivityRepository

    protected abstract val path: String

    override fun getResponse(context: JobContext, pageNo: Int, hasTotal: Boolean): JSONObject {
        val (store, _, _, parameter) = context
        val request = buildRequest(parameter, pageNo)
        val client = applicationContext.getBean(AkcClient::class.java)
        val response = client.execute(store, path, request)
        if (response.getString("status") != "success") {
            throwException(context, path, response)
        }
        return response.getJSONObject("data")
    }

    protected abstract fun buildRequest(parameter: Any?, pageNo: Int): Map<String, Any>
}

// 爱库存活动
@Component
class AkcActivityPorter : GenericPorter(), PlatformIdentity.AiKuCun {

    @Autowired
    private lateinit var client: AkcClient

    @Autowired
    protected lateinit var akcActivityRepository: AkcActivityRepository

    private val path = "/api/v2/activity/list"

    override fun getId(store: Store) = "akcActivity"

    override fun fetchAndProcess(context: JobContext) {
        val store = context.store
        val request = mapOf("status" to "9")
        val response = client.execute(store, path, request)
        if (response.getString("status") != "success") {
            throwException(context, path, response)
        }
        return response
            .getJSONObject("data")
            .getJSONArray("list")
            .forEach {
                val value = it.toJSONObject()
                val activity = AkcActivity(store, value)
                val oldActivity = akcActivityRepository.findByIdOrNull(activity.id)
                if (oldActivity == null || oldActivity != activity) {
                    akcActivityRepository.saveAndFlush(activity)
                }
            }
    }
}

// 订单
@Component
class AkcTradePorter : AkcPorter() {

    override val pageSize = 1000

    override val path = "/api/v2/order/listall"

    override val documentType = DocumentType.TRADE

    override fun getParameters(store: Store): Pair<List<Any>, Boolean> {
        val akcActivity = akcActivityRepository.findBySidAndCompleted(store.id, false)
        return akcActivity to true
    }

    override val checkParameters = true

    override fun getCount(context: JobContext, response: JSONObject): Int = response.getInteger("totalrecord")

    override fun buildDocuments(context: JobContext, response: JSONObject): List<Document> {
        return response
            .getJSONArray("list")
            .map {
                val value = it.toJSONObject()
                val sn = value.getString("adorderid")
                val status = value.getString("status")
                val modified = (value.getString("paytime")
                    ?: value.getString("ordertime")).toLocalDateTime()
                Document(sn, status, modified, value)
            }
    }

    override fun afterExecuted(context: JobContext) {
        // 爱库存的活动结束24小时后才能停止拉单
        val akcActivity = context.parameter!! as AkcActivity
        val endTime: LocalDateTime = akcActivity.endTime
        val isAfter = LocalDateTime.now().isAfter(endTime.plusHours(24))
        if (isAfter) {
            akcActivityRepository.saveAndFlush(akcActivity.copy(completed = true))
        }
    }

    override fun buildRequest(parameter: Any?, pageNo: Int): Map<String, Any> {
        parameter as AkcActivity
        return mapOf(
            "activityid" to parameter.id,
            "page" to pageNo,
            "pagesize" to pageSize,
        )
    }
}